﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using DataObjects;
using System.Net;
using System.IO;
using Newtonsoft.Json;

namespace GT5RemoteMobile.Services
{
    /// <summary>
    /// Summary description for RaceUpdate
    /// </summary>
    public class RaceUpdate : IHttpHandler, IRequiresSessionState
    {
        Profile psnUser;
        RemoteRaceData currentRace;
        List<RemoteRaceDriver> currentDrivers;
        string jsessionId;

        public void ProcessRequest(HttpContext context)
        {
            psnUser = (Profile)context.Session["psnUser"];
            currentRace = (RemoteRaceData)context.Session["currentRace"];
            currentDrivers = (List<RemoteRaceDriver>)context.Session["currentDrivers"];
            jsessionId = context.Session["jsessionid"].ToString();
            context.Response.ContentType = "application/json";

            if (string.IsNullOrEmpty(context.Request.QueryString["monitorid"]))
            {
                // no monitor id, so we need to get one (or close the race)
                string queryString = "job=" + (int)RemoteRaceJobType.GET_STATUS;
                bool success = false;
                int retryCount = 5;
                while (!success)
                {
                    try
                    {
                        if (retryCount == 0)
                            break;
                        GetRaceStatus(context, queryString);
                        success = true;
                    }
                    catch (Exception)
                    {
                        success = false;
                        retryCount--;
                    }
                }

                if (!success)
                    context.Response.Write("{\"error\":\"Error communicating with GT5 server...try again\"}");
            }
            else
            {
                // we have a monitor id, so we don't need one, but need to update it
                // no monitor id, so we need to get one
                bool success = false;
                int retryCount = 5;
                while (!success)
                {
                    try
                    {
                        if (retryCount == 0)
                            break;
                        GetRaceStatus(context);
                        success = true;
                    }
                    catch (Exception)
                    {
                        success = false;
                        retryCount--;
                    }
                }

                if (!success)
                    context.Response.Write("{\"error\":\"Error communicating with GT5 server...try again\"}");
            }
        }

        private void GetRaceStatus(HttpContext context)
        {
            string queryString = "job=" + (int)RemoteRaceJobType.GET_MONITORLIST +
                "&online_id=" + HttpUtility.UrlEncode(psnUser.ID) +
                "&user_number=" + psnUser.Number +
                "&bspec_monitor_id=" + context.Request.QueryString["monitorid"];
            HttpWebRequest raceStatusRequest = WebRequest.Create(new Uri("https://us.gran-turismo.com/us/api/gt5/remoterace/")) as HttpWebRequest;
            raceStatusRequest.Method = "POST";
            StreamWriter writer = new StreamWriter(raceStatusRequest.GetRequestStream());

            writer.Write(queryString);
            writer.Close();
            raceStatusRequest.CookieContainer = new CookieContainer();
            raceStatusRequest.Headers.Add("Cookie", jsessionId);
            raceStatusRequest.Accept = "text/javascript, text/html, application/xml, text/xml, */*";
            raceStatusRequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";

            using (HttpWebResponse response = raceStatusRequest.GetResponse() as HttpWebResponse)
            {
                StreamReader responseStream = new StreamReader(response.GetResponseStream());
                string json = responseStream.ReadToEnd();

                if (json.Contains("Race finished"))
                {
                    // send job 12
                    // close the race
                    string queryString2 = "job=" + (int)RemoteRaceJobType.END_RACE;
                    HttpWebRequest raceEndRequest = WebRequest.Create(new Uri("https://us.gran-turismo.com/us/api/gt5/remoterace/")) as HttpWebRequest;
                    raceEndRequest.Method = "POST";
                    StreamWriter writer2 = new StreamWriter(raceEndRequest.GetRequestStream());

                    writer2.Write(queryString2);
                    writer2.Close();
                    raceEndRequest.CookieContainer = new CookieContainer();
                    raceEndRequest.Headers.Add("Cookie", jsessionId);
                    raceEndRequest.Accept = "text/javascript, text/html, application/xml, text/xml, */*";
                    raceEndRequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
                    raceEndRequest.GetResponse();
                    context.Response.Write("{\"status\":0}");
                }
                else
                {
                    context.Response.Write(json);
                }
            }
        }

        private void GetRaceStatus(HttpContext context, string queryString)
        {
            HttpWebRequest raceStatusRequest = WebRequest.Create(new Uri("https://us.gran-turismo.com/us/api/gt5/remoterace/")) as HttpWebRequest;
            raceStatusRequest.Method = "POST";
            StreamWriter writer = new StreamWriter(raceStatusRequest.GetRequestStream());

            writer.Write(queryString);
            writer.Close();
            raceStatusRequest.CookieContainer = new CookieContainer();
            raceStatusRequest.Headers.Add("Cookie", jsessionId);
            raceStatusRequest.Accept = "text/javascript, text/html, application/xml, text/xml, */*";
            raceStatusRequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";

            using (HttpWebResponse response = raceStatusRequest.GetResponse() as HttpWebResponse)
            {
                StreamReader responseStream = new StreamReader(response.GetResponseStream());
                string json = responseStream.ReadToEnd();

                // check if race is finished
                if (json.Contains("\\\"status\\\":0"))
                {
                    // send job 12
                    // close the race
                    string queryString2 = "job=" + (int)RemoteRaceJobType.END_RACE;
                    HttpWebRequest raceEndRequest = WebRequest.Create(new Uri("https://us.gran-turismo.com/us/api/gt5/remoterace/")) as HttpWebRequest;
                    raceEndRequest.Method = "POST";
                    StreamWriter writer2 = new StreamWriter(raceEndRequest.GetRequestStream());

                    writer2.Write(queryString2);
                    writer2.Close();
                    raceEndRequest.CookieContainer = new CookieContainer();
                    raceEndRequest.Headers.Add("Cookie", jsessionId);
                    raceEndRequest.Accept = "text/javascript, text/html, application/xml, text/xml, */*";
                    raceEndRequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
                    raceEndRequest.GetResponse();
                    context.Response.Write("{\"status\":0}");
                }
                else
                {
                    // return the monitor id
                    context.Response.Write(json);
                }
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}